"""
响应体
"""

import urllib.parse

from pydantic import BaseModel
from starlette.responses import (
    JSONResponse,
    StreamingResponse,
)

import utils.enum_utils as enum
from models.other import FileStream
from my_typing import *


class APIResponse(JSONResponse):
    """ 自定义 | 响应体 """

    def __init__(
        self,
        code: enum.HTTPStatusCode = enum.HTTPStatusCode.HTTP_200_OK,
        message: StrOrNone = None,
        data: DictOrNone = None,
        errors: ListStr | None = None,
        headers: Mapping[str, str] | None = None,
        media_type: StrOrNone = None,
    ) -> None:
        """
        Args:
            code: 响应状态码（默认为 200）
            message: 消息
            data: 数据
            errors: 错误提示
            headers: 响应头
            media_type: 媒体类型
        """

        body: dict = {
            "code": code,
            "message": message or code.label_en,
            "data": data or {},
            "errors": errors or [],
        }

        super().__init__(
            content=body,
            status_code=enum.HTTPStatusCode.HTTP_200_OK,
            headers=headers,
            media_type=media_type,
        )


class OKResponse(APIResponse):
    """ 成功 | 响应 | 不携带数据 """

    def __init__(self) -> None:
        super().__init__()


class OKWithDataResponse(APIResponse):
    """ 成功 | 响应 | 携带响应数据 """

    def __init__(self, vo: BaseModel) -> None:
        super().__init__(data=vo.model_dump())


class ErrorResponse(APIResponse):
    """ 失败 | 响应 | 携带错误信息 """

    def __init__(
        self,
        errors: ListStr,
        code: enum.HTTPStatusCode = enum.HTTPStatusCode.HTTP_400_BAD_REQUEST,
    ) -> None:
        super().__init__(
            code=code,
            errors=errors,
        )


class ExceptionResponse(APIResponse):
    """ 异常 | 响应 | 系统内部错误 """

    def __init__(self) -> None:
        super().__init__(code=enum.HTTPStatusCode.HTTP_500_INTERNAL_SERVER_ERROR)


class FileResponseBase(StreamingResponse):
    """ 文件响应 | 基类 """

    disposition: ClassVar[str] = ""
    """ 文件的处置方式或展示方式 """

    def __init__(self, file_stream: FileStream) -> None:
        quote_filename: str = urllib.parse.quote(file_stream.filename)
        super().__init__(
            BytesIO(file_stream.content),
            media_type=file_stream.media_type,
            headers={
                "Content-Disposition": (
                    f"{self.disposition}; "
                    f"filename={quote_filename}; "
                    f"filename*=utf-8''{quote_filename}"
                )
            },
        )


class FileViewResponse(FileResponseBase):
    """ 文件浏览 | 响应 """

    disposition: ClassVar[str] = "inline"
    """
    - 浏览器会尝试在浏览器窗口中直接显示文件内容
    - 适用于图片、PDF、文本等可以在浏览器中直接预览的文件
    - 用户体验更好，因为可以直接查看文件内容
    """


class FileDownloadResponse(FileResponseBase):
    """ 文件下载 | 响应 """

    disposition: ClassVar[str] = "attachment"
    """
    - 浏览器会弹出"保存"对话框，提示用户下载文件
    - 强制用户下载文件而不是在浏览器中打开
    - 适用于需要用户保存到本地的文件，如 Excel、Word 等文档
    """
